/*
 * 主程序启动
 * 
 */
package com.zhouxujing.game;

import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.FileInputStream;

import javax.swing.JFrame;
import javax.swing.JPanel;


/**游戏内有五种状态0,-1,1,2,3,4 表示0游戏未开始，-1游戏进入选择关卡，1游戏运行中，2游戏暂停，3游戏失败,4游戏成功,6充钱页面
 *让测试类继承JPanel类后不在闪烁
 */
public  class MyGameFrame extends JPanel {
	
	public static Image plane_img;//飞机图片
	private Image bg;//背景
	private Image main;//游戏初始界面

	
	private Image supply_img;//
	
	public static MyPlane plane;//创建我的飞机类
	public static BossPlane bossPlane;
	public  static Image bossImage;
	public static Thread bossThread;
	
	private Image army_images[];//敌机的图片

	private Plane armys[];//敌机对象数组集合
	private Image offScreenImage;//图片越界
	private int score;//得分
	private SupplyPacket supply;//补给包对象
	public static  int state = 0;//状态码
	public static  int  step = 3;//战机初始速度值
	private static Image charge;
	private static Image pay;
	
	public static Thread paintThread;//绘制线程
	public static Thread planefire;//战机火力线程
	private Thread armysfire[];//敌机火力线程
	private Thread supplyThread;//补给包线程

	

	/**
	 * 加载方法
	 * 获取图片资源
	 */
	public void load(){
		
	
	//获取我方战机的图
		plane_img=GameUtil.getImage("images/planex.png");
		//获取充钱图标
		charge = GameUtil.getImage("images/charge.png");
		pay = GameUtil.getImage("images/pay.jpg");
		
		Blood.count = 5;
	    //获取背景图片
		main = GameUtil.getImage("images/main.jpg");
		bg=GameUtil.getImage("images/bg0.jpg");
		bossImage = GameUtil.getImage("images/boss.png");
		//下面6个敌机图片，用数组存
		army_images=new Image[6];
		for(int i=0;i<army_images.length;i++){
			army_images[i] = GameUtil.getImage("images/army/army"+(i+1)+".png");
            army_images[i].getWidth(null);
		}
		//补给包图
		supply_img=GameUtil.getImage("images/supply.png");
		
	}
	/**
	 * 初始化窗口方法
	 * 
	 */
	
	public  void init(int step){
		//设置标题
		
		JFrame jf = new JFrame();
		jf.add(this);
		jf.setTitle("飞机大战");
		//设置可见
		jf.setVisible(true);
		//设置界面的宽度和高度
		jf.setSize(Constant.GAME_WIDTH, Constant.GAME_HEIGHT);
		//设置框架出现位置
		jf.setLocationRelativeTo(null);
		//关闭窗口
		jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		jf.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
		
		//给窗体添加键监听器
		jf.addKeyListener(new KeyMonitors());
		jf.addMouseListener(new MouseAdapter() {
			

			@Override
			public void mouseClicked(MouseEvent e) {
				// TODO Auto-generated method stub
				super.mouseClicked(e);
				
				if (e.getX()>100 && e.getX()<130 && e.getY()>5 && e.getY()<35) {
//					if (state == 1) {
						state = 6;
						System.out.println("将state的值赋值为6");
//					}
					
				}
				//这个是开始游戏的坐标范围
				if (e.getX()>150 && e.getX()<520 && e.getY()>450 && e.getY()<500) {
					//当点击鼠标左键时，将状态码设为1即运行游戏
					if (state == 0) {
						//当我点击开始游戏时，且此时state的值为0时，进入选择关卡模式；
						state = -1;
					}
					
				}
				//鼠标选择关卡模式
				//简单
				else if (e.getX()>150 && e.getX()<350 && e.getY()>150 && e.getY()<200) {
					//表示此时在选择关卡状态
					if (state == -1) {
						state = 1;
						//简单模式双方战机速度为3
						//设置双方子弹
						 MyGameFrame.step = Constant.SIMPLE_STEP;
						 MyPlane.step = Constant.SIMPLE_STEP+1;
						 Plane.step = Constant.SIMPLE_STEP;
						
					}
				}
				//困难
				else if (e.getX()>150 && e.getX()<350 && e.getY()>250 && e.getY()<300) {
					//表示此时在选择关卡状态
					if (state == -1) {
						state = 1;
						//简单模式双方战机速度为3
						//设置双方子弹
						 MyGameFrame.step = Constant.DIFFICULTY_STEP;
						 MyPlane.step =Constant.DIFFICULTY_STEP+1;
						 Plane.step = Constant.DIFFICULTY_STEP;
						 Constant.DEFAULT_PLANE_BC = 80;
						 Constant.DEFAULT_ARMY_BC = 20;
						 Constant.BULLET_STEP=7;
						 
						 Plane.attackspeed = 800;
						 MyPlane.attackspeed=400;
						 Constant.random=0.6;
					}
				}
				//地狱
				else if (e.getX()>150 && e.getX()<350 && e.getY()>350 && e.getY()<400) {
					//表示此时在选择关卡状态
					if (state == -1) {
						state = 1;
						//设置双方子弹
						//简单模式双方战机速度为3
						 MyGameFrame.step = Constant.LIMBO_STEP;
						
						 MyPlane.step =Constant.LIMBO_STEP+1;
						 Plane.step = Constant.LIMBO_STEP;
						 Constant.DEFAULT_PLANE_BC = 100;
						 Constant.DEFAULT_ARMY_BC = 50;
						 Constant.BULLET_STEP=10;
						 Constant.ATTACKSPEED=800;
						 MyPlane.attackspeed=300;
						 Constant.random=0.8;
					}
				}
				//游戏失败 选择退出游戏
				
				else if (e.getX()>50 && e.getX()<300 && e.getY()>600 && e.getY()<650) {
					//表示此时在选择关卡状态
					if (state == 3) {
						
						//简单模式双方战机速度为3
						 System.exit(0);
					}
				}
				//游戏失败，选择重新开始
				else if (e.getX()>370 && e.getX()<620 && e.getY()>600 && e.getY()<650) {
				
					if (state == 3) {
						state = 1;
						Blood.count=5;
						//简单模式双方战机速度为3
						
					}
				}
				//游戏通关
				else if (e.getX()>0 && e.getX()<650 && e.getY()>0 && e.getY()<750) {
					//表示此时在选择关卡状态
					if (state == 4) {
						
						//简单模式双方战机速度为3
						 System.exit(0);
					}
				}
				//点击充钱
				 
			}
		});
		//创建众多类对象，及线程类，并调用run方法
		plane=new MyPlane(plane_img,300,630,Constant.DEFAULT_PLANE_BC,step);//创建我的战机对象，参数有图片，宽和长
		bossPlane = new BossPlane(bossImage, 200.0, 5.0, Constant.DEFAULT_ARMY_BC, step);//创建boss对象
		supply=new SupplyPacket(supply_img);//补给包对象，图片
		armys=new Plane[6];//飞机类数组，6个赋值给敌机类
		
		//给敌机类添加图片
		for(int i=0;i<armys.length;i++){
			armys[i]=new Plane(army_images[i],step);
		}
		//此处设置paint，我方飞机线程，敌方线程
	
		planefire=new Thread(plane);
		bossThread = new Thread(bossPlane);
		armysfire=new Thread[armys.length]; //
		
		for(int i=0;i<armys.length;i++){//
			armysfire[i]=new Thread(armys[i]);
		}
		//补给包线程，多线程同时运行
		supplyThread=new Thread(supply);
		bossThread.start();
		
		planefire.start();
		for(int i=0;i<armys.length;i++){
			armysfire[i].start();
		}
		supplyThread.start();
		new Thread(new Music()).start();
	
	}
	/**
	 * start 启动各个线程对象开始方法
	 */

	/**
	 * 绘画线程类
	 */
	public class PaintThread extends Thread{
		public void run() {
			while(true){
				repaint();
				try{
					Thread.sleep(40);//40毫秒刷新一次，此处修改会影响游戏的速度
				}catch(InterruptedException e){
					e.printStackTrace();
				}
			}
		}
	}
	
	/**
	 * 实现键盘适配器类
	 */
	class KeyMonitors extends KeyAdapter{
//重写了keyAdapter的方法，键按下及键释放方法。这两个方法在myplane类中
		@Override
		public void keyPressed(KeyEvent e) {
			plane.addDirection(e);
			plane.stopGame(e);
			plane.evolution(e);
			plane.shieldPlane(e);
			plane.tenAttackspeed(e);
		
		}
           
		@Override
		public void keyReleased(KeyEvent e) {
			plane.minusDirection(e);
		}
		
	}
	@Override
	/**
	 *绘制背景，当前得分
	 */
	public void paint(Graphics g) {
		
			if (this.state == 0) {
				g.drawImage(main,0,0,null);
	            //改变画笔的颜色
	          g.setColor(Color.red);
	            //改变文字大小和样式
	           g.setFont(new Font("楷体",Font.BOLD,50));
	            //添加文字
	          g.drawString("点击开始游戏",150,450);
	          g.setFont(new Font("楷体",Font.BOLD,20));
	          g.drawString("游戏说明，适当游戏益脑，请过度沉迷游戏！", 70,550 );
	          g.drawString("制作团队周绪敬，邵卓，兰祯淞", 70,580 );
	          g.drawString("方向键wsad,控制上下左右移动，1键增加自身移速", 70,610 );
	          g.drawString("2键我方战机变身，3键开启无敌护盾，重复按取消", 70,640 );
	            
//				System.out.println("游戏未开始");
//				this.state=1;
//				System.out.println("state:"+state);
			}
			else if (this.state == -1) {
				g.drawImage(main,0,0,null);
				//三个选项不同的颜色
				g.setColor(Color.red);
	            //改变文字大小和样式
	           g.setFont(new Font("楷体",Font.BOLD,40));
	            //添加文字
	          g.drawString("简单模式",150,150);
	          
	          g.setColor(Color.red);
	            //改变文字大小和样式
	           g.setFont(new Font("楷体",Font.BOLD,40));
	            //添加文字
	          g.drawString("困难模式",150,250);
	          
	          g.setColor(Color.red);
	            //改变文字大小和样式
	           g.setFont(new Font("楷体",Font.BOLD,40));
	            //添加文字
	          g.drawString("地狱模式",150,350);
			}
			else if (this.state == 1) {
			
					
					g.drawImage(bg, Constant.bgX, Constant.bgY, null);
					
					if (Constant.bgY>=0) {
						Constant.bgY = -750;
					}
					Constant.bgY+=2;
				
				
				//绘制充钱图标
				g.drawImage(charge, 130,5, 30, 30, null);
				drawScore(g);
				//调用补给包绘画
				supply.drawSelf(g);
				//调用我方战机绘画方法
				plane.drawSelf(g);
				bossPlane.drawSelf(g);
				//我方战机 子弹类对象掉用drawself方法
				for(int i=0;i<plane.bullets.length;i++){
					plane.bullets[i].drawSelf(g);
					//System.out.println("已调用我方战机子弹绘制方法");
				}
				//boss
				for(int i=0;i<bossPlane.bullets.length;i++){
					bossPlane.bullets[i].drawSelf(g);
					//System.out.println("已调用boss子弹绘制方法");
				}
				//敌机对象掉用绘画方法
				for(int i=0;i<armys.length;i++){
					armys[i].drawSelf(g);
				}
				//给每一个敌机对象的子弹调用绘画方法
				for(int i=0;i<armys.length;i++){
					for(int j=0;j<armys[i].bullets.length;j++){
						armys[i].bullets[j].drawSelf(g);
					}
				}
				//给我方战机的血条调用绘画方法
				plane.blood.draw(g);
				isCollide();//判断是否碰撞
				
				System.out.println("当前速度plane"+MyPlane.step);
				System.out.println("当前速度enemy"+Plane.step);
			
			}
		
			else if (this.state == 2) {
				 g.setColor(Color.red);
		            //改变文字大小和样式
		            g.setFont(new Font("楷体",Font.BOLD,50));
		            //添加文字
		            g.drawString("游戏暂停，再次按空格继续",6,370);
						}
			else if(state == 3){
	            //改变画笔的颜色
	            g.setColor(Color.red);
	            //改变文字大小和样式
	            g.setFont(new Font("楷体",Font.BOLD,50));
	            //添加文字
	            g.drawString("您已被击败！得分："+score,50,350);
	            g.drawString("退出游戏", 50, 600);
	            g.drawString("选择复活", 370, 600);
	            
	        }
	        //通关显示内容
			else if (state == 4){
	            //改变画笔的颜色
	            g.setColor(Color.green);
	            //改变文字大小和样式
	            g.setFont(new Font("仿宋",Font.BOLD,50));
	            //添加文字
	            g.drawString("游戏通关!",210,300);
	            g.drawString("点击屏幕任意区域退出游戏！",0, 600);
	        }
		
			else if(state == 6) {
				System.out.println("执行绘制二维码");
				g.drawImage(pay, 50, 50, 400, 400, null);
			}
		
			
	}
	/**
	 * 双缓存图片
	 */
	public void update(Graphics g) {
	    if(offScreenImage == null)
	        offScreenImage = this.createImage(Constant.GAME_WIDTH,Constant.GAME_HEIGHT);//
	     
	    Graphics gOff = offScreenImage.getGraphics();
	    paint(gOff);
	    g.drawImage(offScreenImage, 0, 0, null);
	   
	}
	
	public void paintAll() {
		paintThread = new PaintThread();
		paintThread.start();
	}
	/**
	 * 判断是否碰撞！
	 */
	public void isCollide(){
		//遍历敌机集合
		for(int i=0;i<armys.length;i++){
			boolean peng=false;//判断碰撞，初始值为FALSE
			for(int j=0;j<plane.bullets.length;j++){
				if(plane.bullets[j].isLive()&&//当我方子弹存在，且与敌机碰撞时
						(armys[i].getRect().intersects
								(plane.bullets[j].getRect()))){
					peng=true;
					plane.bullets[j].setLive(false);//将碰撞到的敌机live设置为FALSE
					score+=10;//得分加等10
					break;//退出当前循环
				}
				else{//
					continue;
				}
			}
			if(peng){//如果碰撞了则
				armys[i].setCollide(true);//设置敌机已被碰撞
				if(armys[i].explode1.count==0){//此时未绘制爆炸动图
					armys[i].explode1.setLocation(armys[i].getX(), armys[i].getY());//在符合条件的敌机位置设置一个爆炸对象
					armys[i].ex1=true;//ex1是一个boolean值
				}
				else{//否则此时在绘制爆炸动图，表示可以同时绘制两个爆炸动画，增加画面流畅
					armys[i].explode2.setLocation(armys[i].getX(), armys[i].getY());
					armys[i].ex2=true;//表示这架敌机爆炸
				}
					armys[i].setLive(false);//然后将这架敌机的live设置为FALSE，表示已死亡
			}//
			for(int j=0;j<armys[i].bullets.length;j++){//j的值小于敌机的子弹的数量，循环的次数登云敌机的子弹数量
				//如果敌机的子弹与我方战机相碰，则我方飞机血量减少,我方战机与敌方飞机碰撞,我方血量减少
				if(armys[i].bullets[j].isLive()&&(armys[i].bullets[j].getRect().intersects
						(plane.getRect()))  || armys[i].isLive() &&  armys[i].getRect().intersects(plane.getRect())){
					plane.blood.minusBlood();
					armys[i].bullets[j].setLive(false);//然后设置敌机子弹消失
				}
			}//我方飞机与敌机碰撞
			if (armys[i].isLive() &&  armys[i].getRect().intersects(plane.getRect())) {
				plane.blood.minusBlood();
				score+=10;
				armys[i].setCollide(true);//设置敌机已被碰撞
				if(armys[i].explode1.count==0){//此时未绘制爆炸动图
					armys[i].explode1.setLocation(armys[i].getX(), armys[i].getY());//在符合条件的敌机位置设置一个爆炸对象
					armys[i].ex1=true;//ex1是一个boolean值
				}
				else{//否则此时在绘制爆炸动图，表示可以同时绘制两个爆炸动画，增加画面流畅
					armys[i].explode2.setLocation(armys[i].getX(), armys[i].getY());
					armys[i].ex2=true;//表示这架敌机爆炸
				}
					armys[i].setLive(false);//然后将这架敌机的live设置为FALSE，表示已死亡
			}
		}
		//下面判断boss与我方战机碰撞，boss子弹与我方战机碰撞，我方子弹与boss碰撞
		if (bossPlane.isLive() && bossPlane.getRect().intersects(plane.getRect())) {
			plane.blood.minusBlood();//当我方战机与boss碰撞时，我方血量-1；boss不受影响
			
		}
		//我方子弹与boss碰撞
		for (int j = 0; j < plane.bullets.length; j++) {
			if (plane.bullets[j].isLive() && plane.bullets[j].getRect().intersects(bossPlane.getRect())) {
				bossPlane.count--;
				//System.out.println("boss受伤，血量减一！"+bossPlane.count);//当boss血量为0时，设置boss爆炸
				bossPlane.setCollide(true);//设置敌机已被碰撞
				
				if (bossPlane.count <= 0) {
					if(bossPlane.explode1.count==0){//此时未绘制爆炸动图
						bossPlane.explode1.setLocation(bossPlane.getX()+60, bossPlane.getY());//在符合条件的boss敌机位置设置一个爆炸对象
						bossPlane.ex1=true;//ex1是一个boolean值
					}
					else{//否则此时在绘制爆炸动图，表示可以同时绘制两个爆炸动画，增加画面流畅
						bossPlane.explode2.setLocation(bossPlane.getX(), bossPlane.getY());//在符合条件的boss敌机位置设置一个爆炸对象
						bossPlane.ex2=true;//ex1是一个boolean值
					}
						bossPlane.setLive(false);//然后将这架敌机的live设置为FALSE，表示已死亡
						score+=400;//击杀boss得分
						bossPlane.count = 20;//每次死后血量回满
				}
				plane.bullets[j].setLive(false);
			}
			
		}
		//boss子弹与我方战机碰撞，我方战机血量减少
		for (int j = 0; j < bossPlane.bullets.length; j++) {
			if (bossPlane.bullets[j].isLive() && bossPlane.bullets[j].getRect().intersects(plane.getRect())) {
				plane.blood.minusBlood();
			//	System.out.println("我方战机被boss子弹击中受伤，血量减一！");
				bossPlane.bullets[j].setLive(false);
			}
			
		}
		if(supply.isLive()&&plane.isLive()//判断当补给包与我方战机碰到时，我方战机血量增加，然后，设置补给包live为FALSE
				&&plane.getRect()
				.intersects(supply.getRect())){
			plane.blood.addBlood();
			supply.setLive(false);
		}//
	}
	/**
	 * 绘制得分
	 */
	public void drawScore(Graphics g){
		//判断分数是否达标
		if (score >= 5000) {
			state = 4;
		}
		Color c=g.getColor();
		g.setColor(Color.WHITE);
		g.setFont(new Font("楷体", Font.BOLD, 20));
		g.drawString("得分："+score, 20, 25);
		g.setColor(c);
	}
	public static void main(String[] args) {
		MyGameFrame f=new MyGameFrame();
	    f.paintAll();
		f.load();
		f.init(step);
	}

}
